use std::sync::Arc;
use async_trait::async_trait;
use mongodb::bson::{Document, Bson};
use anyhow::Result;

/// 存储提供者接口
/// 定义了所有非泛型的数据库操作抽象方法，用于隐藏具体数据库实现细节
#[async_trait]
pub trait IStorage: Send + Sync {
    /// 获取文档集合
    fn get_document_collection(&self, db_name: &str, collection_name: &str) -> Box<dyn ICollection<Document>>;
    
    /// 运行数据库命令
    async fn run_command(&self, db_name: &str, command: Document) -> Result<Document>;
    
    /// 列出所有集合名称
    async fn list_collections(&self, db_name: &str) -> Result<Vec<String>>;
    
    /// 插入单个文档（使用Document类型）
    async fn insert_one_document(&self, db_name: &str, collection_name: &str, document: Document) -> Result<()>;
    
    /// 批量插入文档（使用Document类型）
    async fn insert_many_documents(&self, db_name: &str, collection_name: &str, documents: Vec<Document>) -> Result<()>;
    
    /// 查找文档（返回Document类型）
    async fn find_documents(&self, db_name: &str, collection_name: &str, filter: Document) -> Result<Vec<Document>>;
    
    /// 查找单个文档（返回Document类型）
    async fn find_one_document(&self, db_name: &str, collection_name: &str, filter: Document) -> Result<Option<Document>>;
    
    /// 更新单个文档
    async fn update_one(
        &self,
        db_name: &str,
        collection_name: &str,
        filter: Document,
        update: Document,
    ) -> Result<()>;
    
    /// 批量更新文档
    async fn update_many(
        &self,
        db_name: &str,
        collection_name: &str,
        filter: Document,
        update: Document,
    ) -> Result<()>;
    
    /// 删除单个文档
    async fn delete_one(
        &self,
        db_name: &str,
        collection_name: &str,
        filter: Document,
    ) -> Result<()>;
    
    /// 聚合操作
    async fn aggregate(
        &self,
        db_name: &str,
        collection_name: &str,
        pipeline: Vec<Document>,
    ) -> Result<Vec<Document>>;
}

/// 存储提供者扩展接口
/// 定义了所有泛型的数据库操作抽象方法
#[async_trait]
pub trait IStorageExt: IStorage + Send + Sync {
    /// 获取集合
    fn get_collection<T>(&self, db_name: &str, collection_name: &str) -> Box<dyn ICollection<T>>
    where
        T: serde::Serialize + serde::de::DeserializeOwned + Unpin + Send + Sync + 'static;
    
    /// 插入单个文档
    async fn insert_one<T>(&self, db_name: &str, collection_name: &str, document: T) -> Result<()>
    where
        T: serde::Serialize + serde::de::DeserializeOwned + Unpin + Send + Sync + 'static;
    
    /// 批量插入文档
    async fn insert_many<T>(&self, db_name: &str, collection_name: &str, documents: Vec<T>) -> Result<()>
    where
        T: serde::Serialize + serde::de::DeserializeOwned + Unpin + Send + Sync + 'static;
    
    /// 查找文档
    async fn find<T>(&self, db_name: &str, collection_name: &str, filter: Document) -> Result<Vec<T>>
    where
        T: serde::Serialize + for<'de> serde::Deserialize<'de> + Unpin + Send + Sync + 'static;
    
    /// 查找单个文档
    async fn find_one<T>(&self, db_name: &str, collection_name: &str, filter: Document) -> Result<Option<T>>
    where
        T: serde::Serialize + for<'de> serde::Deserialize<'de> + Unpin + Send + Sync + 'static;
}

/// 集合接口
/// 定义了对特定集合的操作
#[async_trait]
pub trait ICollection<T: serde::Serialize + serde::de::DeserializeOwned + Unpin + Send + Sync>: Send + Sync {
    /// 插入单个文档
    async fn insert_one(&self, document: T) -> Result<()>;
    
    /// 批量插入文档
    async fn insert_many(&self, documents: Vec<T>) -> Result<()>;
    
    /// 查找文档
    async fn find(&self, filter: Document) -> Result<Vec<T>>;
    
    /// 查找单个文档
    async fn find_one(&self, filter: Document) -> Result<Option<T>>;
    
    /// 更新单个文档
    async fn update_one(&self, filter: Document, update: Document) -> Result<()>;
    
    /// 批量更新文档
    async fn update_many(&self, filter: Document, update: Document) -> Result<()>;
    
    /// 删除单个文档
    async fn delete_one(&self, filter: Document) -> Result<()>;
    
    /// 聚合操作
    async fn aggregate(&self, pipeline: Vec<Document>) -> Result<Vec<Document>>;
}

/// 存储提供者类型枚举
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StorageType {
    Mongo,
    PostgreSQL,
}

/// 存储提供者工厂
pub struct StorageProvider;

impl StorageProvider {
    /// 根据配置创建存储实例
    pub async fn create(storage_type: StorageType, connection_string: &str) -> Result<Arc<dyn IStorage>> {
        match storage_type {
            StorageType::Mongo => {
                // 创建MongoDB存储实例
                let mongo_storage = crate::storage::mongo_storage::MongoStorage::new(connection_string).await?;
                Ok(Arc::new(mongo_storage))
            },
            StorageType::PostgreSQL => {
                // 创建PostgreSQL存储实例
                let pg_storage = crate::storage::pg_storage::PgStorage::new(connection_string).await?;
                Ok(Arc::new(pg_storage))
            },
        }
    }
    
    /// 从配置中创建存储实例
    pub async fn from_config() -> Result<Arc<dyn IStorage>> {
        let config = crate::config::Config::load()?;
        let storage_type = match config.db_type() {
            crate::config::DatabaseType::Mongo => StorageType::Mongo,
            crate::config::DatabaseType::PostgreSQL => StorageType::PostgreSQL,
        };
        let connection_string = config.db_connection_string();
        
        Self::create(storage_type, &connection_string).await
    }
}